import { useState, useEffect } from 'react';
import { Table, message, Select, Space, Button, Form, Input, Tag } from 'antd';
const { Option } = Select;
import { experimentPlanService, experimentCourseService, courseService, teacherService, laboratoryService } from '@/service';
import { executeActionAfterReq } from '@/util/errorHandle';
import styles from './index.less';

function ExperimentPlanPage() {
  const [planEpTimeObject, setPlanEpTimeObject] = useState({
    flag: false,
    epTime: 0,
  });
  const [planTIds, setPlanTIds] = useState([]);
  const [planLId, setPlanLId] = useState(-1);
  const [showDialog, setShowDialog] = useState(false);
  const [action, setAction] = useState('NONE');
  const [canPlan, setCanPlan] = useState(false);
  const [canChange, setCanChange] = useState(true);
  const [experimentPlanData, setExperimentPlanData] = useState([]);
  const [experimentCourseData, setExperimentCourseData] = useState([]);
  const [allTeacherData, setAllTeacherData] = useState([]);
  const [allLaboratoryData, setAllLaboratoryData] = useState([]);
  const [teacherData, setTeacherData] = useState([]);
  const [laboratoryData, setLaboratoryData] = useState([]);
  useEffect(() => {
    initData();
  }, []);
  useEffect(() => {
    filterDataBasedOnEpTime();
  }, [planEpTimeObject.flag]);

  const initData = () => {
    getAllExperimentPlan();
    getAllExperimentCourse()
    getAllTeacher();
    getAllLaboratory();
  }
  const getAllExperimentPlan = async () => {
    const res = await experimentPlanService.getAllExperimentPlan().catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(res, () => {
      setExperimentPlanData(res?.data?.map((item: any) => ({
        ...item,
        capacity: item?.Laboratory?.capacity,
        cId: item?.ExperimentCourse?.cId,
      })));
    })
  }
  const getAllExperimentCourse = async () => {
    const res = await experimentCourseService.getAllExperimentCourse().catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(res, () => {
      setExperimentCourseData(res?.data);
    })
  }
  const getAllTeacher = async () => {
    const res = await teacherService.getAllTeacher().catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(res, () => {
      setTeacherData(res?.data);
      setAllTeacherData(res?.data);
    })
  }
  const getAllLaboratory = async () => {
    const res = await laboratoryService.getAllLaboratory().catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(res, () => {
      const data = res?.data?.filter((item: any) => item?.available || true);
      setLaboratoryData(data);
      setAllLaboratoryData(data);
    })
  }

  const columns = [
    {
      title: '实验编号',
      dataIndex: 'ecId',
      key: 'ecId',
      sorter: (a: any, b: any) => a.ecId - b.ecId,
      sortDirections: ['ascend'],
    },
    {
      title: '批次号',
      dataIndex: 'epBatch',
      key: 'epBatch',
      sorter: (a: any, b: any) => a.epBatch - b.epBatch,
      sortDirections: ['ascend'],
    },
    {
      title: '实验时间',
      dataIndex: 'epTime',
      key: 'epTime',
      render: (text: any) => <>{
        `第${Math.floor(text / 100)}周周${Math.floor(text / 10 % 10)}${['', '上午', '下午', '晚上'][text % 10]}`
      }</>,
    },
    {
      title: '实验员',
      dataIndex: 'tIds',
      key: 'tIds',
      filters: allTeacherData.map((item: any) => ({
        text: item?.tId,
        value: item?.tId,
      })),
      onFilter: (value: any, record: any) => 
        record?.tIds?.split(',')?.map((item: any) => Number(item))?.includes(value),
      render: (text: any) => <>{
        text?.split(',')
          ?.filter((item: any) => item)
          ?.map((item: any) => (
            <Tag color="blue" key={item}>
              {item}
            </Tag>
          ))
      }</>,
      width: '100px',
    },
    {
      title: '实验室编号',
      dataIndex: 'lId',
      key: 'lId',
      filters: allLaboratoryData.map((item: any) => ({
        text: item?.lId,
        value: item?.lId,
      })),
      onFilter: (value: any, record: any) => record?.lId == value,
    },
    {
      title: '批次人数',
      dataIndex: 'capacity',
      key: 'capacity',
    },
    {
      title: '实验总人数',
      dataIndex: 'epStudentNumber',
      key: 'epStudentNumber',
    },
    {
      title: '操作',
      key: 'action',
      render: (text: any, record: any) => (
        <Space size="middle">
          <Button type="link" size ="small" className={styles.link} onClick={() => handleEdit(record)}>修改</Button>
          <Button type="link" size ="small" className={styles.link} onClick={() => handleDel(record)} danger>删除</Button>
        </Space>
      ),
    },
  ];

  const [form] = Form.useForm();
  form.setFieldsValue({});
  
  const handleEdit = (record: any) => {
    const { epTime = 0 } = record
    const tIds = record?.tIds?.split(',')?.filter((item: any) => item)?.map((item: any) => Number(item));
    setPlanTIds(tIds);
    setPlanLId(record?.lId);
    onWeekOfSemesterChange(Math.floor(epTime / 100));
    onWeekChange(Math.floor(epTime / 10 % 10));
    onPeriodChange(epTime % 10);
    setCanPlan(true);
    setCanChange(false);
    form.resetFields();
    form.setFieldsValue({
      ...record,
      tIds,
      weekOfSemester: Math.floor(record?.epTime / 100),
      week: Math.floor(record?.epTime / 10 % 10),
      period: record?.epTime % 10,
    });
    setShowDialog(true);
    setAction('EDIT');
  }
  const delOperator = async (record: any) => {
    console.log("🚀 ~ file: index.tsx ~ line 165 ~ delOperator ~ record", record)
    const ecId = record?.ecId;
    const cId = experimentCourseData?.find((item: any) => ecId == item?.ecId)?.cId;
    const epTime = record?.epTime;
    const lId = record?.lId;

    // 修改实验室表
    let lIsArranged = allLaboratoryData?.find((item: any) => lId == item?.lId)?.lIsArranged || '';
    if (lIsArranged?.includes(epTime)) {
      lIsArranged = lIsArranged?.replace(`,${epTime}`, '');
    }
    await laboratoryService.updateLaboratory({
      lId,
      lIsArranged,
    })

    // 删除实验安排表
    const result = await experimentPlanService.destroyExperimentPlan(record).catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(result, async () => {
      await getAllExperimentPlan();
    })

    // 删除实验安排表后，根据该表修改 tIds
    const epRes = await experimentPlanService.getAllExperimentPlan().catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(epRes, async () => {
      // 修改实验课程表
      const experimentPlan = epRes?.data?.filter((item: any) => ecId == item?.ecId);
      let tIds = new Set();
      experimentPlan?.forEach((item: any) => {
        tIds = new Set([...tIds, ...(item?.tIds?.split(',') || [])]);
      })
      await experimentCourseService.updateExperimentCourse({
        ecId,
        tIds: tIds?.join(','),
      });

      // 修改课程表
      const ecRes = await experimentCourseService.getAllExperimentCourse().catch(() => {
        message.error('请求错误');
      });
      executeActionAfterReq(ecRes, async () => {
        const experimentCourse = ecRes?.data?.filter((item: any) => cId == item?.cId);
        let tIds = new Set();
        experimentCourse?.forEach((item: any) => {
          tIds = new Set([...tIds, ...(item?.tIds?.split(',') || [])]);
        })
        await courseService.updateCourse({
          cId: cId,
          tIds: tIds?.join(','),
        });
      })

      await initData();
    })
    
    // 修改实验员表
    const restTIds = epRes?.data?.filter((item: any) => ecId == item?.ecId)
      ?.map((item: any) => item?.tIds)
      ?.map((item: any) => item?.split(','))
      ?.flat() || [];
    Promise.all(
      record?.tIds?.split(',')
        ?.filter((item: any) => item)
        ?.map(async (tId: any) => {
          let ecIds = allTeacherData?.find((item: any) => tId == item?.tId)?.ecIds;
          let cIds = allTeacherData?.find((item: any) => tId == item?.tId)?.cIds;
          let tIsArranged = allTeacherData?.find((item: any) => tId == item?.tId)?.tIsArranged || '';
          console.log("🚀 ~ file: index.tsx ~ line 228 ~ Promise.all ~ allTeacherData", allTeacherData, tId, tIsArranged)
          
          if (!restTIds?.includes(tId)) {
            ecIds = ecIds?.replace(`,${ecId}`, '');
            cIds = cIds?.replace(`,${cId}`, '');
          }
          if (tIsArranged?.includes(epTime)) {
            tIsArranged = tIsArranged?.replace(`,${epTime}`, '');
          }
          await teacherService.updateTeacher({
            tId,
            ecIds,
            cIds,
            tIsArranged,
          })
        })
    )
  }
  const handleDel = async (record: any) => {
    await delOperator(record).then(() => {
      message.info('删除成功');
    });
  }
  const handleAdd = () => {
    setPlanTIds([]);
    setPlanLId(-1);
    setCanPlan(false);
    setCanChange(true);
    form.resetFields();
    form.setFieldsValue({
      epTime: 0
    });
    setShowDialog(true);
    setAction('ADD');
  }
  const handleCancel = () => {
    setShowDialog(false);
    setPlanEpTimeObject({
      ...planEpTimeObject,
      flag: false,
    });
  }

  const handleSubmit = async (values: any) => {
    console.log("🚀 ~ file: index.tsx ~ line 265 ~ handleSubmit ~ values", values)
    if (action === 'EDIT') {
      const recore = experimentPlanData?.find((item: any) => values?.ecId == item?.ecId && values?.epBatch == item?.epBatch);
      await delOperator(recore);
      await addOperator(values).then(() => {
        message.info('修改成功');
        setPlanEpTimeObject({
          ...planEpTimeObject,
          flag: false,
        });
      });
    } else if (action === 'ADD') {
      await addOperator(values).then(() => {
        message.info('添加成功');
        setPlanEpTimeObject({
          ...planEpTimeObject,
          flag: false,
        });
      });
    } else {
      message.error('指定动作错误');
    }

    await initData();
  }

  const addOperator = async (values: any) => {
    console.log("🚀 ~ file: index.tsx ~ line 280 ~ addOperator ~ values", values)
    // 此逻辑只能实现新增操作造成的表改动，无法实现修改操作造成的表改动
    // 因为不知道修改的是那个数据
    // 修改逻辑太复杂了，通过删除+新增来实现
    const ecId = values?.ecId;
    const cId = experimentCourseData?.find((item: any) => ecId == item?.ecId)?.cId;
    const epTime = values?.epTime;
    const lId = values?.lId;

    // 修改实验员表
    Promise.all(
      (typeof values?.tIds === 'string' 
        ? values?.tIds?.split(',')?.filter((item: any) => item) 
        : values?.tIds)
        ?.map(async (tId: any) => {
          let ecIds = allTeacherData?.find((item: any) => tId == item?.tId)?.ecIds || '';
          let cIds = allTeacherData?.find((item: any) => tId == item?.tId)?.cIds || '';
          let tIsArranged = allTeacherData?.find((item: any) => tId == item?.tId)?.tIsArranged || '';
          console.log("🚀 ~ file: index.tsx ~ line 333 ~ Promise.all ~ allTeacherData", allTeacherData, tId, tIsArranged)
          
          if (!ecIds?.includes(ecId)) {
            ecIds = `${ecIds},${ecId}`
          }
          if (!cIds?.includes(cId)) {
            cIds = `${cIds},${cId}`
          }
          if (!tIsArranged?.includes(epTime)) {
            tIsArranged = `${tIsArranged},${epTime}`
          }
          await teacherService.updateTeacher({
            tId,
            ecIds,
            cIds,
            tIsArranged,
          })
        })
    )

    // 修改实验室表
    let lIsArranged = allLaboratoryData?.find((item: any) => lId == item?.lId)?.lIsArranged || '';
    if (!lIsArranged?.includes(epTime)) {
      lIsArranged = `${lIsArranged},${epTime}`
    }
    await laboratoryService.updateLaboratory({
      lId,
      lIsArranged,
    })
    
    // 修改实验课程表
    const ecRes = await experimentCourseService.getAllExperimentCourse().catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(ecRes, async () => {
      const experimentCourse = ecRes?.data?.filter((item: any) => cId == item?.cId);
      let tIds = experimentCourse?.find((item: any) => ecId == item?.ecId)?.tIds || '';
      values?.tIds?.forEach((tId: any) => {
        if (!tIds?.includes(tId)) {
          tIds = `${tIds},${tId}`
        }
      });
      await experimentCourseService.updateExperimentCourse({
        ecId,
        tIds,
      })

      // 修改课程表
      const ecResAfterUp = await experimentCourseService.getAllExperimentCourse().catch(() => {
        message.error('请求错误');
      });
      executeActionAfterReq(ecResAfterUp, async () => {
        const experimentCourse = ecResAfterUp?.data?.filter((item: any) => cId == item?.cId);
        let setTIds = new Set();
        experimentCourse?.forEach((item: any) => {
          setTIds = new Set([...setTIds, ...(item?.tIds?.split(',') || [])]);
        })
        await courseService.updateCourse({
          cId,
          tIds: setTIds?.join(','),
        });
      })
    })

    // 增加实验安排
    values.tIds = values?.tIds?.join(',');
    const epRes = await experimentPlanService.appendExperimentPlan(values).catch(() => {
      message.error('请求错误');
    });
    executeActionAfterReq(epRes, async () => {
      await getAllExperimentPlan();
      setShowDialog(false);
    })
  }

  const onEcIdChange = (value: string | Number) => {
    const weekOfSemester = (experimentCourseData?.find((item: any) => value === item.ecId))?.arrangeWeekly;
    form.setFieldsValue({
      ecId: value,
      epStudentNumber: (experimentCourseData?.find((item: any) => value === item.ecId))?.totalNumber,
      weekOfSemester,
    });
    onWeekOfSemesterChange(weekOfSemester);
  }
  const onTeacherChange = (value: Array<Number>) => {
    form.setFieldsValue({
      tIds: value,
    });
  }
  const onLaboratoryChange = (value: Number) => {
    form.setFieldsValue({
      lld: value,
      capacity: allLaboratoryData?.find((item: any) => value == item?.lId)?.capacity
    });
  }
  const onWeekOfSemesterChange = (value: Number) => {
    let epTime = form.getFieldValue('epTime') || 0;
    const weekOfSemester = Math.floor(epTime / 100);
    const week = Math.floor(epTime / 10 % 10);
    const period = epTime % 10;
    epTime = value * 100 + week * 10 + period;
    form.setFieldsValue({
      epTime,
    });
    setPlanEpTimeObject({
      flag: Boolean(value && week && period),
      epTime,
    });
  }
  const onWeekChange = (value: Number) => {
    let epTime = form.getFieldValue('epTime') || 0;
    const weekOfSemester = Math.floor(epTime / 100);
    const week = Math.floor(epTime / 10 % 10);
    const period = epTime % 10;
    epTime = weekOfSemester * 100 + value * 10 + period;
    form.setFieldsValue({
      epTime,
    });
    setPlanEpTimeObject({
      flag: Boolean(weekOfSemester && value && period),
      epTime,
    });
  }
  const onPeriodChange = (value: Number) => {
    let epTime = form.getFieldValue('epTime') || 0;
    const weekOfSemester = Math.floor(epTime / 100);
    const week = Math.floor(epTime / 10 % 10);
    const period = epTime % 10;
    epTime = weekOfSemester * 100 + week * 10 + value;
    form.setFieldsValue({
      epTime,
    });
    setPlanEpTimeObject({
      flag: Boolean(weekOfSemester && week && value),
      epTime,
    });
  }

  const filterDataBasedOnEpTime = () => {
    const { flag, epTime } = planEpTimeObject;
    setCanPlan(flag);
    if (!flag) {
      return;
    }
    setTeacherData(allTeacherData?.filter((item: any) => (
      planTIds.includes(item?.tId)
      || !((item?.tIsArranged || '')
        ?.split(',')
        ?.map((item: any) => Number(item))
        ?.find((item: any) => epTime === item)
      )
    )))
    setLaboratoryData(allLaboratoryData?.filter((item: any) => (
      planLId == item?.lId
      || !((item?.lIsArranged || '')
        ?.split(',')
        ?.map((item: any) => Number(item))
        ?.find((item: any) => epTime === item)
      )
    )))
  }
  
  return (
    <div className={styles.experimentPlan}>
      <Button type="primary" className={styles.add} onClick={handleAdd}>安排实验</Button>
      <Table dataSource={experimentPlanData} columns={columns} style={{minHeight: "520px"}} />
      <div className={styles.formdiv} style={{display: showDialog ? 'block' : 'none'}}>
        <Form
          name="basic"
          labelCol={{ span: 5 }}
          wrapperCol={{ span: 16 }}
          form={form}
          autoComplete="off"
          onFinish={handleSubmit}
          className={styles.form}
        >
          <Form.Item label="实验编号" name="ecId" rules={[{ required: true }]}>
            <Select
              allowClear
              placeholder="请选择"
              onChange={onEcIdChange}
              disabled={!canChange}
            >
              {
                experimentCourseData?.map(((item: any) => (
                  <Option value={item?.ecId}>{`${item?.ecId}: ${item?.ecTitle}`}</Option>
                )))
              }
            </Select>
          </Form.Item>
          <Form.Item label="批次号" name="epBatch" rules={[{ required: true }]}>
            <Input disabled={!canChange} />
          </Form.Item>
          <Form.Item label="实验时间" name="epTime">
            <Input.Group compact>
              <Form.Item name='weekOfSemester' noStyle rules={[{ required: true }]}>
                <Select
                  style={{ width: '33.33%' }}
                  placeholder="周次"
                  onChange={onWeekOfSemesterChange}
                  disabled
                >
                  {
                    Array.from({length: 20}).map((v, k) => k + 1).map((item: any) => (
                      <Option value={item}>{item}</Option>
                    ))
                  }
                </Select>
              </Form.Item>
              <Form.Item name='week' noStyle rules={[{ required: true }]}>
                <Select
                  style={{ width: '33.33%' }}
                  placeholder="周几"
                  onChange={onWeekChange}
                >
                  {
                    Array.from({length: 7}).map((v, k) => k + 1).map((item: any) => (
                      <Option value={item}>{`${['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'][item]}`}</Option>
                    ))
                  }
                </Select>
              </Form.Item>
              <Form.Item name='period' noStyle rules={[{ required: true }]}>
                <Select
                  style={{ width: '33.33%' }}
                  placeholder="时段"
                  onChange={onPeriodChange}
                >
                  {
                    [1, 2, 3].map((item: any) => (
                      <Option value={item}>{`${['', '上午', '下午', '晚上'][item]}`}</Option>
                    ))
                  }
                </Select>
              </Form.Item>
            </Input.Group>
          </Form.Item>
          <Form.Item label="实验员" name="tIds" rules={[{ required: true }]}>
            <Select
              mode="multiple"
              allowClear
              placeholder="请先确定实验时间再选择"
              disabled={!canPlan}
              onChange={onTeacherChange}
            >
              {
                teacherData.map((item: any) => (
                  <Option value={item?.tId}>{`${item?.tId}: ${item?.tName}`}</Option>
                ))
              }
            </Select>
          </Form.Item>
          <Form.Item label="实验室编号" name="lId" rules={[{ required: true }]}>
            <Select
              allowClear
              placeholder="请先确定实验时间再选择"
              disabled={!canPlan}
              onChange={onLaboratoryChange}
            >
              {
                laboratoryData.map((item: any) => (
                  <Option value={item?.lId}>{`${item?.lId}: ${item?.location}`}</Option>
                ))
              }
            </Select>
          </Form.Item>
          <Form.Item label="批次人数" name="capacity" rules={[{ required: true }]}>
            <Input disabled />
          </Form.Item>
          <Form.Item label="实验总人数" name="epStudentNumber" rules={[{ required: true }]}>
            <Input disabled />
          </Form.Item>
          <Form.Item wrapperCol={{ offset: 5, span: 16 }}>
            <Button type="primary" htmlType="submit">
              确认
            </Button>
            <Button type="link" htmlType="button" onClick={handleCancel}>
              取消
            </Button>
          </Form.Item>
        </Form>
        <div className={styles.cover} onClick={handleCancel}></div>
      </div>
    </div>
  );
}

export default ExperimentPlanPage;
